home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Delphi Magazine Collection 2001
/
Delphi Magazine Collection 20001 (2001).iso
/
DISKS
/
Issue61
/
Contract
/
AccountExample.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
2000-08-07
|
4KB
|
159 lines
unit AccountExample;
interface
uses
classes;
type
{ forward declarations }
TAccountLine = class;
TSimpleAccount = class
private
FBalance: Currency;
FBalanceCalculated: Boolean;
FLines: TList;
function CalculateBalance: Currency;
function GetBalance: Currency;
function GetAccountLine(Index: Integer): TAccountLine;
function GetLineCount: Integer;
protected
function InternalGetAccountLine(Index: Integer): TAccountLine;
procedure AssertInvariants; virtual;
public
constructor Create;
destructor Destroy; override;
function AddLine(const Text: string; Amount: Currency): TAccountLine;
property Balance: Currency read GetBalance;
property Lines[Index: Integer]: TAccountLine read GetAccountLine;
property LineCount: Integer read GetLineCount;
end;
TAccountLine = class
private
FText: string;
FAmount: Currency;
procedure SetText(const Value: string);
public
constructor Create(const AText: string; AAmount: Currency);
property Text: string read FText write SetText;
property Amount: Currency read FAmount;
end;
const
S_PreFailed = 'Pre-Condition failed: ';
S_PostFailed = 'Post-Condition failed: ';
S_InvFailed = 'Invariant-Condition failed: ';
implementation
uses
contnrs;
{ TSimpleAccount }
function TSimpleAccount.AddLine(const Text: string;
Amount: Currency): TAccountLine;
procedure AssertPre;
begin
AssertInvariants;
Assert(Length(Text) > 0,S_PreFailed + 'Lenght(Text) must be > 0');
Assert(Amount<> 0,S_PreFailed + 'Ammount must be <> 0');
end;
procedure AssertPost;
begin
AssertInvariants;
Assert(Assigned(Result),'Result does not contain a valid AccountLine object');
end;
begin
AssertPre;
Result := TAccountLine.Create(Text,Amount);
FLines.Add(Result);
{ uncomment the next line to fix AssertInvariants failure }
FBalanceCalculated := False;
AssertPost;
end;
procedure TSimpleAccount.AssertInvariants;
begin
if FBalanceCalculated then begin
Assert(FBalance = CalculateBalance,S_InvFailed + 'Balance out of Sync');
end;
end;
function TSimpleAccount.CalculateBalance: Currency;
var
I: Integer;
begin
Result := 0;
for I := 0 to Pred(LineCount) do begin
Result := Result + InternalGetAccountLine(I).Amount;
end;
end;
constructor TSimpleAccount.Create;
begin
FLines := TObjectList.Create(True);
end;
destructor TSimpleAccount.Destroy;
begin
FLines.Free;
inherited Destroy;
end;
function TSimpleAccount.GetAccountLine(Index: Integer): TAccountLine;
procedure AssertPre;
begin
AssertInvariants;
Assert((Index > -1) and (Index < LineCount),
S_PreFailed + 'Index must be > -1 and < Count');
end;
begin
AssertPre;
Result := InternalGetAccountLine(Index);
end;
function TSimpleAccount.GetBalance: Currency;
begin
if not FBalanceCalculated then begin
FBalance := CalculateBalance;
FBalanceCalculated := True;
end;
Result := FBalance;
end;
function TSimpleAccount.GetLineCount: Integer;
begin
Result := FLines.Count;
end;
function TSimpleAccount.InternalGetAccountLine(
Index: Integer): TAccountLine;
begin
Result := FLines[Index];
end;
{ TAccountLine }
constructor TAccountLine.Create(const AText: string; AAmount: Currency);
begin
FText := AText;
FAmount := AAmount;
end;
procedure TAccountLine.SetText(const Value: string);
begin
FText := Value;
end;
end.